Skip to content

feat: 场景驱动调度 — workflow 可配置引擎 + prompt 外部化 + 架构图重绘#12

Merged
JiGuangWorker merged 13 commits into
mainfrom
feature/role-upgrade
Jul 5, 2026
Merged

feat: 场景驱动调度 — workflow 可配置引擎 + prompt 外部化 + 架构图重绘#12
JiGuangWorker merged 13 commits into
mainfrom
feature/role-upgrade

Conversation

@JiGuangWorker

@JiGuangWorker JiGuangWorker commented Jul 5, 2026

Copy link
Copy Markdown
Owner

Summary

Issue #11 核心重构:将 code-bee 的调度策略从硬编码四阶段 harness 重构为 YAML workflow 配置驱动的可编排引擎。用户可通过 --workflow--prompts-dir 完全自定义角色体系和调度流程,无需修改代码。

12 个 Commits 按功能域分组

🏗️ 配置基础设施(Schema + Workflow)

  • 5481c8c feat(schema): add workflow schema and config loader — 三层 JSON Schema 定义(draft-07)、YAML 加载器、语义校验(工具引用完整性/别名唯一性/stage 可见性)、87.6% 测试覆盖率
  • 1f77397 refactor(schema): unify schema files to YAML format — 9 个 schema 定义文件统一为 YAML,与用户配置格式一致

⚙️ Runtime 可编排引擎

  • abcc923 feat(runtime): implement configurable workflow engine — 新建 internal/runtime 包,包含 7 个核心组件:Engine、ToolRegistry(3 种 Tool 类型)、AgentTool、CommandTool、StageExecutor、ParallelExecutor、LoopExecutor、ExecutionContext、Expression 条件求值、PromptBuilder(5 个内置模板迁入 embed)
  • 7d34eb9 refactor(pipeline): replace hardcoded dispatch with runtime.Engine — dispatch.go 从 624 行减至 152 行,Service 委托 Engine.Run 驱动;新增 ArtifactResolverAdapter 桥接 pipeline ↔ runtime;内置 default_workflow.yaml

🔧 Agent 角色外部化

  • ea0070e refactor(config): externalize agent roles to workflow tools — 删除 BuiltinAgents() 硬编码,角色名从 workflow.Tools 按 prompt_template 派生(display_name > aliases[0] > name 回退链)

📝 文档 + 架构图

  • 21e1299 docs: update README for scenario-driven workflow architecture — 更新项目结构、架构说明、新增「自定义 Workflow」章节
  • 820e5c0 docs(README): redraw architecture diagrams with Mermaid — 3 个实现级 Mermaid 图(分层组件架构/Dispatch 调用时序/配置加载与数据流)+ Engine 终止语义表

🎨 Prompt 模板外部化 + CLI bug 修复

  • ebbf777 feat(runtime): support --prompts-dir — PromptBuilder 支持 overlay 外部模板;Engine Functional Options;--prompts-dir CLI flag;端到端集成测试
  • 5c94219 fix(cli): parse --workflow/--prompts-dir when --repo precedes them — 修复 flag 两阶段解析 bug(--repo--workflow/--prompts-dir 前时后者被静默忽略),smoke test 发现,回归测试覆盖

🧹 CI 修复

  • 04880fb chore: sync go.mod/go.sum via go mod tidy — 修复 // indirect 标记和 gopkg.in/check.v1 缺失
  • 4e1f815 fix(lint): goimports + staticcheck — 修复 4 个 goimports 格式化和 SA4006 未使用变量
  • 55ebe6d fix(lint): reduce cyclomatic complexity — 5 个函数提取 helper 降低复杂度(gocyclo 18-31 → 全部 ≤15),修复 errcheck/unused

变更统计

指标
文件变更 53 files
新增 internal/runtime/ (20 files)、internal/schema/ (15 files)
删除 internal/pipeline/prompts.gointernal/config/builtin_agents.go
重构 internal/pipeline/dispatch.go (624→152 lines)

Testing

  • go build/vet/test ./... 全绿
  • runtime 覆盖率 76.1%,pipeline 70.3%,schema 87.6%,config 100%
  • 3 个端到端集成测试:CompletedPath / BlockedPath / CustomWorkflow
  • CLI 冒烟测试:验证 --prompts-dir 错误路径、--workflow 错误路径、自定义 workflow+prompts 联合加载

Known Gaps

  • issue-post-blocked 阶段因 Engine 遇 Blocked 立即终止而无法运行(README 已记录)
  • FunctionTool 仍为桩实现
  • 后续计划:on_blocked: continue 增强、测试覆盖率提至 85%+

Closes #11

- 三层 JSON Schema (draft-07): tool/stage/condition/loop/pipeline_step/workflow
- 工具别名支持 (name + display_name + aliases), 解决硬编码角色锁定场景问题
- 基于 santhosh-tekuri/jsonschema/v5 的 Schema 校验器, embed 打包
- YAML 配置加载器 + 跨字段语义校验 (工具引用完整性/别名唯一性/stage 可见性)
- 用户配置统一 YAML, JSON 仅用于 schema 定义文件
- 87.6% 测试覆盖率, 含 8 valid + 12 invalid 用例

Refs #11
将 9 个 schema 定义文件从 JSON 转为 YAML 格式,与用户配置格式统一。

改动:
- schemas/v1/*.json → schemas/v1/*.yaml(内容等价,YAML 语法)
- $id 和 $ref 的 URL 保持 .json 后缀作为 URI 标识符(JSON Schema 标准约定)
- loadEmbeddedSchemas: 读 YAML → 转 JSON → 注册到 compiler
- go:embed 改为 *.yaml
- 更新 types.go 注释和 README.md 文件名引用

测试覆盖: 87.0% (全项目测试通过)

Refs #11
新建 internal/runtime 包,实现基于 schema.Workflow 的可配置调度引擎。

核心组件:
- Tool 接口: 统一 agent/command/function 三种工具类型
- AgentTool: 包装 agent.Runner,调用 AI 智能体
- CommandTool: 通过 exec.CommandContext 执行 shell 命令
- ToolRegistry: 支持 name + alias 查找
- ExecutionContext: stage 间数据传递 + loop 状态维护
- Expression: 结构化 ExitCondition 求值(6 operator)+ 字符串表达式
- StageExecutor: 串行执行(when/on_blocked/input_from)
- ParallelExecutor: 并行执行(all/any/first_success 三种 join)
- LoopExecutor: 循环执行(exit_when/judge/max_iterations/max_consecutive_unknown)
- Engine: 顶层入口,消费 *schema.Workflow

Prompt 模板外部化:
- prompts/*.md: 5 个模板文件(coding/review/issue-handling/issue-post/loop-judge)
- PromptBuilder: 从 embed FS 加载 text/template 渲染

测试覆盖: 76.9% (76 个测试用例)
全项目测试通过

Refs #11
Stage 8 of scenario-driven scheduling refactor.

- dispatch.go: 624 -> 152 lines; Service now holds *runtime.Engine and
  *schema.Workflow, Dispatch delegates to engine.Run
- delete prompts.go; 5 prompt templates migrated to
  internal/runtime/prompts/*.md (rendered by prompt_builder.go)
- add runtime_adapter.go: ArtifactResolverAdapter bridges
  pipeline.ArtifactSet <-> runtime.ArtifactResolver, routing LoadResult
  by stage name to typed loaders
- add runtime/default_workflow.{go,yaml}: go:embed built-in default
  workflow; --workflow flag supports external override
- cmd/worker/main.go: serviceFactory signature returns error to surface
  workflow load failures; --workflow flag wired through buildService
- tests: add TestToPipelineResult + 2 end-to-end integration tests
  (BlockedPath, CompletedPath); drop 9 dispatch state-machine tests
  whose behavior is now covered by internal/runtime engine tests
- .gitignore: anchor 'worker' pattern to repo root ('/worker') so
  cmd/worker/ is no longer ignored; add .trae/

Known gap: issue-post-blocked stage removed -- Engine terminates on
Blocked, so the stage could never run. issue-handling BLOCKED now
returns Blocked directly without posting a blocking comment. Future
Engine enhancement (on_blocked: continue) can restore this.

Verification: go build/vet/test all pass; runtime 76.1%, pipeline 70.3%
coverage.

Refs: #11
Complete Issue #11 verification standard: agent role definitions are
now loaded from workflow config, no longer hardcoded in BuiltinAgents().

- delete Config fields: DefaultAgent, ReviewerAgent, IssuePostAgent,
  LoopJudgeAgent, MaxCodingReviewRounds, LoopJudgeStartRound
  (last 3 were dead code; first 3 now derived from workflow)
- delete BuiltinAgents(), AgentByName(), AgentNames(), AgentRole struct
  (dead code: only config_test.go self-tested them)
- delete defaultMaxCodingReviewRounds / defaultLoopJudgeStartRound consts
- add runtime.lookupDisplayNameByPromptTemplate: derives display name
  from workflow.Tools by prompt_template, with fallback chain
  display_name > aliases[0] > name > empty
- modify agent_tool.buildPromptData: derive DefaultAgent/ReviewerAgent/
  IssuePostAgent from EC.Workflow instead of Config
- Config now holds only Repo/IssueNumber/GitHubToken (3 runtime params)
- update tool_test.go: add testWorkflow helper, pass workflow to
  IssueHandling test so prompt derivation works
- add TestLookupDisplayNameByPromptTemplate (5 sub-cases)
- update config_test.go: drop BuiltinAgents tests, simplify defaults test

Backward compatible: default workflow's display_names match the old
hardcoded values (developer/QA lead/PM), so prompts render identically
without --workflow flag.

Verification: go build/vet/test pass; runtime 76.5%, config 100% coverage.

Refs: #11
Complete Issue #11 documentation standard: explain how to customize
scheduling strategy via workflow config.

- update 'why code-bee' bullets: replace '极简内核' with '场景驱动调度'
- update tech stack table: scheduler now describes workflow-driven orchestration
- add architecture overview with ASCII pipeline diagram
- update usage example: add --workflow flag, fix output message
- update project structure: add internal/runtime/ and internal/schema/,
  refresh package descriptions
- add '自定义 Workflow' section: config structure, 3编排原语, 3 tool types,
  role name derivation, links to schema/default-workflow/prompts
- update roadmap: mark scenario-driven scheduling, composable pipeline,
  tool aliases as completed; add on_blocked recovery item

Refs: #11
- PromptBuilder 加载外部目录 .md 模板,overlay 同名内置模板
- Engine 通过 Functional Options 接收 WithPromptsDir
- Service 透传 EngineOption,CLI 新增 --prompts-dir flag
- 新增 overlay 单元测试 + 自定义 workflow 端到端集成测试

Closes #11 (prompts externalization gap)
Two-stage flag parsing had a bug: parseWorkflowFlag and parsePromptsDirFlag
each registered only a single flag in their own FlagSet. Go's flag package
stops parsing at the first unregistered flag, so when --repo (registered
only in runCLI's FlagSet) appeared before --workflow/--prompts-dir, the
probe functions returned empty strings and the flags were silently ignored
(falling back to builtin workflow / builtin prompts).

Discovered via smoke test: --prompts-dir /nonexistent/prompts did not
error out, and the binary proceeded to dispatch with builtin prompts.

Fix: merge the two probe functions into parseExtraFlags, which registers
all known flags (--repo/--issue/--version as placeholders) so parsing
proceeds past them. Add table-driven regression test covering 6 arg
orderings including the previously broken 'flags after --repo' case.

The same bug affected --workflow since its introduction; this commit
fixes both.
…tion level

Replace the single ASCII tree diagram with three Mermaid diagrams that
show how the architecture is actually implemented:

1. Layered component architecture (flowchart TB) — CLI/pipeline/runtime/
   schema four layers with all key structs (Engine, ToolRegistry,
   StageExecutor, AgentTool, PromptBuilder, ExecutionContext,
   ArtifactResolverAdapter, etc.) and interface-implementation edges
   (ArtifactResolver <- Adapter, Runner <- agent.Runner).

2. Dispatch call chain (sequenceDiagram) — full call timeline from
   runCLI -> Service.Dispatch -> Engine.Run -> StageExecutor ->
   AgentTool -> runner.Run, including result-file reset/read/write
   timing and early-termination semantics.

3. Config loading & data flow (flowchart LR) — workflow dual-source
   (go:embed builtin + --workflow override) and prompt overlay
   (--prompts-dir covers same-name builtin), plus result-file flow
   between stages via ExecutionContext.

Add an Engine termination semantics table documenting how
Blocked/ManualRequired/Completed trigger early return, with a note on
the known issue-post-blocked gap.
- internal/runtime/expression_test.go: goimports formatting
- internal/runtime/loop_executor_test.go: goimports formatting
- internal/schema/loader.go: goimports formatting
- internal/runtime/tool_test.go: SA4006 assign of tool is never used

Found by CI golangci-lint.
…orts

- expression.go: extract evalRegexCondition helper (18→reduced)
- stage_executor.go: extract handleOnBlocked helper (19→reduced)
- agent_tool.go: extract fillCoding/Review/IssuePost/LoopJudgePromptData helpers (30→reduced)
- parallel_executor.go: extract aggregateStatus helper, remove unused base param (28→reduced)
- loop_executor.go: extract executeBody & handleJudge helpers (31→reduced)
- validator.go: check AddResource error, remove unused workflowSchemaPath const
- main.go: add nolint:errcheck for fs.Parse in probe FlagSet
- loop_judge_test.go: add nolint:unused for readLoopHistoryForTest

All found by CI golangci-lint (errcheck, gocyclo, unused, goimports).
Extract postRound helper for per-round maintenance (ConsecutiveUnknown,
judge, LastFeedback). Drops Execute from 18 to <=15 gocyclo threshold.

Found by CI golangci-lint gocyclo check.
@JiGuangWorker JiGuangWorker merged commit e289e71 into main Jul 5, 2026
1 check passed
@JiGuangWorker JiGuangWorker deleted the feature/role-upgrade branch July 5, 2026 15:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Improvement] 蜂巢调度策略应由场景驱动,而非硬编码固定角色

2 participants